﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Threading;
using System.Data.SqlClient;

namespace SQLProxy
{
    class ConsistencyManager
    {
        private string thisConString;
        private string otherConString;
        private int thisDatabase, otherDatabase;
        private DataSet userVersionVector;
        private SqlConnection thisConnection, otherConnection;
        Thread thread;

        public ConsistencyManager(string thisConString, string otherConString, int thisDatabase,
            int otherDatabase, DataSet userVersionVector)
        {
            this.thisConString = thisConString;
            this.otherConString = otherConString;
            this.thisDatabase = thisDatabase;
            this.otherDatabase = otherDatabase;
            this.userVersionVector = userVersionVector;

            this.thisConnection = new SqlConnection(thisConString);
            this.otherConnection = new SqlConnection(otherConString);

            thread = new Thread(new ThreadStart(updateDatabase));
            thread.Start();
        }

        private void updateDatabase()
        {
            /* get user version vector to compare */
            DataTableReader dtReader = userVersionVector.CreateDataReader();
            /* for each vector check if the server's is up-to-date and then bring up-to-date copy */
            thisConnection.Open();
            otherConnection.Open();

            SqlTransaction thisTransaction = thisConnection.BeginTransaction();
            SqlTransaction otherTransaction = otherConnection.BeginTransaction();
            SqlCommand thisCommand = thisConnection.CreateCommand();
            SqlCommand otherCommand = otherConnection.CreateCommand();
            thisCommand.Transaction = thisTransaction;
            otherCommand.Transaction = otherTransaction;

            try {

                Console.WriteLine("> Dados do servidor estao sendo atualizados!");

                /* go through each position in the version vector to update */
                while (dtReader.Read())
                {
                    thisCommand.CommandText = "select server" + otherDatabase + " from version_vector where resi_id=" +
                        dtReader.GetInt32(0);
                    int otherVersion = (int)thisCommand.ExecuteScalar();

                    if (otherVersion < dtReader.GetInt32(otherDatabase))
                    {
                        /* bring the newest copy from the other server */
                        otherCommand.CommandText = "select * from residence where resi_id=" + dtReader.GetInt32(0);
                        SqlDataReader sqlReader = otherCommand.ExecuteReader();

                        /* read data from other server and write on this */
                        if (sqlReader.Read())
                        {
                            Residence auxRes = new Residence(sqlReader, 1);

                            sqlReader.Close();

                            /* update residence */
                            thisCommand.CommandText = "update residence set topology='" + auxRes.Topology +
                                "', cooling=" + auxRes.Cooling + ", heating=" +
                                auxRes.Heating + ", isolation=" + auxRes.Isolation +
                                ", coverage='" + auxRes.Coverage + "', glasses='" + auxRes.Glasses + "', " +
                                "category=" + auxRes.Category + " where resi_id=" + auxRes.Resi_id;
                            thisCommand.ExecuteNonQuery();

                            otherCommand.CommandText = "select server" + otherDatabase + " from version_vector where " +
                                "resi_id=" + dtReader.GetInt32(0);
                            int newValue = (int)otherCommand.ExecuteScalar();

                            /* update version vector */
                            thisCommand.CommandText = "update version_vector set server" + otherDatabase +
                                "=" + newValue + " where resi_id=" + dtReader.GetInt32(0);
                            thisCommand.ExecuteNonQuery();
                        }
                        else
                        {
                            sqlReader.Close();
                        }
                    }
                }

                dtReader.Close();

                thisTransaction.Commit();
                otherTransaction.Commit();

                Console.WriteLine("> Atualizacao do servidor concluida!");
            }
            catch (Exception e)
            {
                thisTransaction.Rollback();
                otherTransaction.Rollback();
            }
            finally
            {
                thisConnection.Close();
                otherConnection.Close();
            }
        }

    }
}
